/**
 * 给一个数，每个节点染色，求所有同色节点之间的路径长度之和
 * 显然点分治或者树上启发式合并均可。
 * 树上启发式合并，对于u节点，只需要统计过u节点的路径即可。
 * 令x是u节点已经统计过的子树，i是当前要统计的某个节点，则i的贡献为
 *          cnt * (Di - 2Du) + sum
 * 其中cnt是已统计过子树中与i节点同色的节点数量，sum是已统计过子树中与i节点同色的节点的深度之和
 * 这二者均可以使用树状数组维护。
 * 对于u节点的每个轻儿子子树的节点，循环统计即可
 * 最后统计u本身的贡献，为 sum - cnt * Du
 */
#include <bits/stdc++.h>
#include <bits/extc++.h>
using namespace std;

using llt = long long;
using vi = vector<int>;
using vll = vector<llt>;
using pii = pair<int, int>;
using pll = pair<llt, llt>;
using Real = long double;

struct FenwickTree{ // 树状数组

using value_type = llt;
using vec_type = vector<value_type>;

int n;
vec_type c;

FenwickTree() = default;

static int lowbit(int x){return x & -x;}

void init(int nn){this->c.assign((this->n=nn) + 1, 0);}

void modify(int pos, value_type delta){
    for(int i=pos;i<=this->n;i+=lowbit(i)) this->c[i] += delta;
}

value_type query(int pos)const{
    value_type ans = 0;
    for(int i=pos;i;i-=lowbit(i)) ans += this->c[i];
    return ans;
}

value_type query(int s, int e)const{return this->query(e) - this->query(s - 1);}

};

FenwickTree BCnt, BSum;

struct dsu_on_tree_t{ // init，输入数据，依次调用dfsHeavy(root, 0), dfs(root, 0, false)

using vi = vector<int>;

int N;
vector<vi> G; // 树, 1-index

struct node_t{ // 树链剖分的结构
    int size; 
    int hson; // 重儿子，这里是原树编号    
    int nid;  // 在树链剖分中的新编号
    int mdes; // 本子树全部在[nid, mdes]之间, 这是剖分编号
};
vector<node_t> Nodes;
vi New2Old;   // 剖分的编号为i，则原树节点编号为New2Old[i], 显然有Nodes[New2Old[i]].nid == i
int TimeStamp;
int Root;

vi Color;
vi Depth;
llt Ans;

void init(int n){
    N = n;
    G.assign(N + 1, {});
    Nodes.assign(N + 1, {0, 0, 0, 0});
    New2Old.assign(N + 1, 0);
    TimeStamp = 0;
    Color.assign(N + 1, 0);
    Depth.assign(N + 1, 0);
    Ans = 0;
}

void mkDiEdge(int a, int b){
    G[a].push_back(b);
}

void mkBiEdge(int a, int b){
    mkDiEdge(a, b);
    mkDiEdge(b, a);
}

void dfsHeavy(int u, int p){ // 递归重儿子
    auto & n = Nodes[u];
    n.size = 1;
    New2Old[n.nid = ++TimeStamp] = u;
    Depth[u] = Depth[p] + 1;

    for(auto v : G[u]){
        if(v == p) continue;

        dfsHeavy(v, u);
        n.size += Nodes[v].size;
        if(Nodes[n.hson].size < Nodes[v].size) n.hson = v;
    }

    n.mdes = TimeStamp;
    return;
}


void dfs(int u, int p, bool keep){ // 递归
    const auto & n = Nodes[u];
    for(auto v : G[u]){
        if(v == p or v == n.hson) continue;
        dfs(v, u, false);
    }
    /// 最后递归重儿子
    if(n.hson) dfs(n.hson, u, true);

    for(auto v : G[u]){
        if(v == p or v == n.hson) continue;

        for(int j,i=Nodes[v].nid;i<=Nodes[v].mdes;++i){
            j = New2Old[i];
            auto cnt = BCnt.query(Color[j], Color[j]);
            auto sum = BSum.query(Color[j], Color[j]);
            Ans += cnt * (Depth[j] - 2LL * Depth[u]) + sum;
        }

        for(int j,i=Nodes[v].nid;i<=Nodes[v].mdes;++i){
            j = New2Old[i];
            BCnt.modify(Color[j], 1);
            BSum.modify(Color[j], Depth[j]);
        }        
    }

    /// 确定u的影响
    auto cnt = BCnt.query(Color[u], Color[u]);
    auto sum = BSum.query(Color[u], Color[u]);
    Ans += sum - cnt * Depth[u];
    BCnt.modify(Color[u], 1);
    BSum.modify(Color[u], Depth[u]);


    /// 是否清空u子树对即时数据的影响
    if(not keep){
        for(int j,i=n.nid;i<=n.mdes;++i){
            j = New2Old[i];
            BCnt.modify(Color[j], -1);
            BSum.modify(Color[j], -Depth[j]);
        }
    }
    return;
}


};

int N;
dsu_on_tree_t Tree;

llt proc(){
    BCnt.init(N);
    BSum.init(N);
    Tree.dfsHeavy(1, 0);
    Tree.dfs(1, 0, true);
    return Tree.Ans;
}

void work(){ 
    cin >> N;
    Tree.init(N);
    for(int u,v,i=1;i<N;++i){
        cin >> u >> v;
        Tree.mkBiEdge(u, v);
    }
    for(int i=1;i<=N;++i) cin >> Tree.Color[i];
    cout << proc() << endl;
    return;
}




int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);	
    int nofkase = 1;
	// cin >> nofkase;
	while(nofkase--) work();
	return 0;
}